.TITLE CEXBF - COMM EXEC .IDENT /01.18/ ; ; Copyright (c) 1995-1999 by Mentec Inc., U.S.A. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; J. PROVINO 3-AUG-78 ; ; MODIFIED BY: ; ; JF005 - J. FORECAST 28-MAR-79 ; ALLOCATE BUFFER SPACE DEPENDING ON CONDITIONAL ASSEMBLY ; PARAMETERS. ; ; JF006 - J. FORECAST 14-MAY-79 ; CHANGE ALLOCATIONS FOR NEW MAPPED COMM/EXEC ; ; JF007 - J. FORECAST 8-AUG-80 ; CHANGE ALLOCATIONS AGAIN ; ; JF008 - J. FORECAST 9-JAN-81 ; CHANGE ALLOCATIONS FOR NEW BUFFER MANAGEMENT SUPPORT ; ; BM244 - B. S. MCCARTHY 11-MAR-82 ; FINAL BUFFER SIZE ADJUSTMENTS FOR RSX-11M-PLUS ; VERSION 2.0 (BASE LEVEL 10) AND ADD DESCRIPTIVE TEXT. ; ; JJ001 - J. Jackson 4-Jan-82 ; Adjust sizing for DECnet 3.0 release ; ; JJ002 - J. Jackson 28-Feb-83 ; Increase size for multiprocessor case ; to include DLC support (for Ethernet) ; ; WD001 - W. Daley 2-Jul-84 ; Combine Comm/Exec modules (CESCH, CELLC, CEDLC, CEDDM, ; CEBUF, CELOG, CETIM). ; Remove L$$SI1 and remaining M$$MGE conditionals. ; Change conditionals for N$$EVL, N$$OPT, and X$$MDC to ; generate code if R$$MPL is defined. ; Remove INHIB$, ENABL$, SAVMAP, RESMAP, and MAP - replace ; with in-line code. ; Change SAVRG and RESRG to local macros. ; Change all I/O page references to absolute. ; Append CESUB module with similar changes to 4.02. ; Remove SCBDF$ and CLKDF$ macros (not used). ; Add DLC$OV and CRC$OV global symbols. ; Add $CEX global entry and M$$NET (network support) conditional. ; ; LA001 - Remove saving of SP in $INTSX ; ; WD002 - Add performance monitor hooks (CHANGED BY LBM004) ; ; LAA002 - Remove conditionals in .TITLE ; ; LAA003 - Add $CXFLG global symbol ; ; WD002 - Modify $CNV22 for Q-bus I/D space support ; ; LBM004 - CHANGE SPM HOOKPOINT IMPLEMENTATION FOR RSX-11M-PLUS V3.0 ; ; GS001 - G Strevell 4-Mar-85 ; Change $CNV22 to use APR bias only when entered with R3 = 0 ; ; 1.14 WMD001 - W. Duane 30-Apr-85 ; Add $CEXND symbol to end of CEXBF. ; ; 1.15 BM369 - B. S. McCarthy 27-Aug-85 ; Reformat SPM hookpoint ; ; 1.16 WJD001 - W. Daley 06-Oct-86 ; Add Global labels and space for NTINIT run time fix of ; SLT offsets and buffer wait code for DECnet-11M-PLUS V4.0 ; ; 1.17 DC100 - D. Carroll 15-Feb-1993 ; Call $FORK on mP system so that we don't deallocate primary ; pool if we don't own the executive lock, even though we may ; own the Comm/Exec lock ... ; ; 1.18 DC404 - D. Carroll 18-Oct-1995 ; Include PSECT statement to allow ICB pool to be fully expanded ; during sysgen ; ; $CEX:: ; THIS SYMBOL MUST ALWAYS BE DEFINED FOR ; MCRS "SET /NOCEX" COMMAND TO BUILD ; CORRECTLY .IF DF M$$NET .SBTTL Macro Definitions ; ; Macro Library Calls ; .MCALL CCBDF$,OPTDF$,PDVDF$,SLTDF$ CCBDF$ ; Define the CCB offsets OPTDF$ <=>,<:> ; Define COMM/EXEC options PDVDF$ ; Define the PDV offsets SLTDF$ ; Define the SLT offsets .IIF DF,K$$DAS&I$$CBP, .PSECT EXEC1 ;DC404 ; ; Local Macro Definitions ; .IF DF K$$DAS .MACRO DDFDF,FNC,ARG1 MOV R3,-(SP) ; Save R3 MOV #FNC,R3 ; Get function code .IF B BR DDCM1 ; Common processing for non-CCB control function .IFF ; B .IF IDN , BR DDCM2 ; Common processing for modem control functions .IFF ; IDN , .IF IDN , BR DDCM4 .IFF ; IDN , BR DDCM3 ; Common processing for control functions with CCB .ENDC ; IDN , .ENDC ; IDN , .ENDC ; B .ENDM DDFDF .IFF ; DF K$$DAS .MACRO DDFDF,FNC,ARG1 .IF B JSR R3,DDCM1 ; Common processing for non-CCB control function .IFF ; B .IF IDN , JSR R3,DDCM2 ; Common processing for modem control functions .IFF ; IDN , .IF IDN , JSR R3,DDCM4 .IFF ; IDN , JSR R3,DDCM3 ; Common processing for control functions with CCB .ENDC ; IDN , .ENDC ; IDN , .ENDC ; B 10$: .WORD FNC .ENDM .ENDC ; DF K$$DAS .MACRO SAVRG LIST .IRP R, MOV R,-(SP) .ENDM .ENDM .MACRO RESRG LIST .IRP R, MOV (SP)+,R .ENDM .ENDM .SBTTL Symbol Definitions ; ; These symbols are global for use by DECnet processes. ; DLC$OV == 8. ; Data link layer overhead (bytes) CRC$OV == 4. ; CRC overhead (bytes) $CXFLG == CF.MDM!CF.DDM!CF.DYN!CF.EIS!CF.LOG ; Comm exec options ;;K.CSR == 0 ; ??? ; ; Define offsets to saved PSW from $INHIB. This offset is used by the ; FAIL entry (refer to BUFGT) to set the C-Bit so that failures to allocate ; an RDB, LDB, or SDB will set the C-Bit on the ENABL$. ; .IF NDF M$$PRO PRIOFF=0 ; Offset to Saved Priority .IFF ; NDF M$$PRO PRIOFF=2 ; Extra word on Stack for Multi-Processors .ENDC ; NDF M$$PRO .SBTTL $INTSX - Comm Exec Device Interrupt Save Routine ;+ ; **-$INTSX-COMM EXEC DEVICE INTERRUPT SAVE ROUTINE ; ; Called by: JSR R4,$INTSX ; ; Inputs: ; R5 = Pointer to priority specification in device line table ; ; Outputs: ; The System Stack Depth is decremented, and if zero a switch ; to the System Stack is effected. ; ; R5 = Pointer to word following device priority ;- $INTSX:: ;+ ; ** W a r n i n g ** ; ; SPM hookpoint number 36. ; ; Do not change the instruction following ; label without checking SPM ;- $SPH36==. ;SPM changes the instruction at ;the location of this label DEC @#$STKDP ;;; Decrement Stack Depth Indicator BIC (R5)+,PS ;; Lower priority to device level .IF DF M$$PRO CACHE$ SAVE ;; Save bypass state of cache .ENDC ; DF M$$PRO CALL @R4 ;; Call caller back .IF DF M$$PRO CACHE$ UNSAVE ;; Restore bypass state of cache .ENDC ; DF M$$PRO MTPS #PR7 ;; Inhibit Interrupts .IF DF K$$DAS ;; Slightly different for RSX-11M+ ;; with Kernel Data Space enabled MOV 4(SP),@#KINAR5 ;; Restore previous I-Space APR Contents MOV 6(SP),@#KISAR5 ;; Restore previous D-Space APR Contents ;; Current contents of stack: ;; R4 (Saved by JSR R4,$INTSX in DDM) ;; R5 (Saved by JSR R5,'ISR' in Line Table) ;; KINAR5 (Saved in Line Table) ;; KISAR5 (Saved in Line Table) ;; PS (Saved by Interrupt) ;; PC (Saved by Interrupt) MOV (SP)+,2(SP) ;; Move saved R4 down on stack MOV (SP)+,2(SP) ;; Move saved R5 down on stack ;; Contents of stack (necessary for $INTXX) ;; R4 (Saved by JSR R4,$INTSX in DDM) ;; R5 (Saved by JSR R5,'ISR' in Line Table) ;; PS (Saved by Interrupt) ;; PC (Saved by Interrupt) .IFF ;; DF K$$DAS MOV 4(SP),@#KISAR5 ;; Restore previous APR contents ;; Current contents of stack: ;; R4 (Saved by JSR R4,$INTSX in DDM) ;; R5 (Saved by JSR R5,'ISR' in Line Table) ;; KISAR5 (Saved in Line Table) ;; PS (Saved by Interrupt) ;; PC (Saved by Interrupt) MOV 2(SP),4(SP) ;; Move saved R5 down on stack MOV (SP)+,(SP) ;; Move saved R4 down on stack ;; Contents of stack (necessary for $INTXX) ;; R4 (Saved by JSR R4,$INTSX in DDM) ;; R5 (Saved by JSR R5,'ISR' in Line Table) ;; PS (Saved by Interrupt) ;; PC (Saved by Interrupt) .ENDC ;; DF K$$DAS JMP $INTX1 ;; Return through RSX Interrupt exit ;sjp0005 .SBTTL $INTX7 - Level 7 Interrupt Exit ;+ ; **- $INTX7 - LEVEL 7 INTERRUPT EXIT ; ; This routine is used by Driver ISRs that run at priority level ; 7 during some portion of Interrupt Service. Drivers ISRs may ; only push one item on the stack during level 7 interrupt ; service, and must call $INTSX (to drop priority and switch to ; the system stack) to post any completions. ; ; Inputs: (stack must be formatted as follows:) ; R5 (Saved in line table) ; * KINAR5 (Saved in line table for RSX-11M+ only) ; KISAR5 (Saved in line table) ; PS (Saved by interrupt) ; PC (Saved by interrupt) ;- $INTX7:: MOV (SP)+,R5 ;;; Restore R5 .IF DF K$$DAS ;;; Different for RSX-11M+ ;;; with Kernel Data Space enabled MOV (SP)+,@#KINAR5 ;;; Restore Kernel I-Space APR5 .ENDC ; DF K$$DAS MOV (SP)+,@#KISAR5 ;;; Restore Kernel mapping register 5 RTI ;;; Return from Interrupt .SBTTL $PDSPL - Set Up a Process Level and Dispatch to it ;+ ; **-$PDSPL-SET UP A PROCESS LEVEL AND DISPATCH TO IT ; ; This subroutine is called to set up the level of a process ; and dispatch to it. This routine assumes that the stack is formatted ; properly for a pass through the scheduler when the dispatched process ; exits. ; ; Inputs: ; R2 = PDV Index (word index) ; R3 = Address of function code ; R4 = Address of a CCB (optional) ; R5 = Address of a Line Table (optional) ; ; Outputs: ; The new process execution priority is established and dispatch ; is performed by the routine '$PDDSP'. ; ;- $PDSPL::MTPS #PR7 ;;; Disable Interrupts MOV R2,R1 ;;; Copy PDV Index ADD $PDVTA,R1 ;;; Point into PDV Index Table MOV (R1),R1 ;;; Get address of process' PDV BICB Z.SCH(R1),PS ;; Set priority of process .SBTTL $PDDSP - Dispatch to a Process ;+ ; **-$PDDSP-DISPATCH TO A PROCESS ; ; Inputs: ; R2 = PDV Index (word index) ; R3 = Address of function code ; R4 = Address of a CCB (optional) ; R5 = Address of a process line table (optional) ; ; Outputs to the Process: ; Based on the PDV Index in R2, the process is entered at the ; entry point specified by the function code pointed to by R3 ; with: ; R3 = Subfunction code (word index) ; R4 = Address of a CCB (optional) ; R5 = Address of process line table (optional) ; ; R2 through R5 need not be preserved by the called process ;- $PDDSP:: ; ref label MOV $CMPDV,-(SP) ; Save Current Process PDV Index MOV R2,$CMPDV ; Load new Process PDV Index ADD $PDVTA,R2 ; Point into PDV Index Table MOV (R2),R2 ; Get PDV Address MOV @#KISAR6,-(SP) ; Save current Kernel APR 6 MOV @#KISAR5,-(SP) ; Save current process mapping .IF DF K$$DAS MOV @#KINAR6,-(SP) ; Save instruction APR'S MOV @#KINAR5,-(SP) MOV (R2),@#KINAR5 ; Map process in both I and D space .ENDC ; DF K$$DAS MOV (R2)+,@#KISAR5 ; Map to process MOV (R2),-(SP) ; Save address of dispatch table MOVB (R3)+,R2 ; Get function code (no sign extend) ADD (SP)+,R2 ; Form address of entry in dispatch table BIT #1,(R2) ; Is this a dispatch to an odd address? BNE 10$ ; If NE, yes! - bad dispatch. MOVB (R3)+,R3 ; Set up subfunction code CALL @(R2)+ ; Call process .IF DF K$$DAS MOV (SP)+,@#KINAR5 ; Restore instruction APRs MOV (SP)+,@#KINAR6 .ENDC ; DF K$$DAS MOV (SP)+,@#KISAR5 ; Restore previous process mapping MOV (SP)+,@#KISAR6 ; Restore previous APR 6 contents MOV (SP)+,$CMPDV ; Restore previous process PDV index RETURN ; And return to caller ; ; at crash: ; R2 -> computed address of dispatch table entry. ; R3-1 -> byte of function code. ; R3 -> byte of subfunction code. ; R4 = optional CCB address. ; R5 = optional line table address. ; 10$: IOT ; Crash on odd dispatch. .SBTTL $PDQUE - Queue a CCB (Chain) to a List and Schedule Process ;+ ; **-$PDQUE-QUEUE A CCB CHAIN TO A LIST AND SCHEDULE PROCESS ; ; Inputs: ; R3 = PDV Index (high byte) and channel number (low byte) ($PDQUE ONLY) ; R4 = Address of first CCB in a chain. The last CCB of the chain ; has a zero next CCB pointer. ; ; Outputs: ; The PDV Index and channel number parameters are stored in the CCB ; and the CCB (or chain) is linked to the operation queue for the ; process defined by the PDV index and a schedule request for that ; process is set. ; ; Registers modified: ; R3 and R4 ;- $PDQUE::MOV R3,C.LIN(R4) ; Store PDV index and channel number $PDQU1::MOV R5,-(SP) ; Save callers R5 MOV R4,R5 ; Copy address of first CCB 10$: BIC #CS.LST,C.STS(R4) ; Clear last CCB marker MOV R4,R3 ; Copy current CCB address MOV (R3),R4 ; Get next CCB address BNE 10$ ; If NE keep going BIS #CS.LST,C.STS(R3) ; Mark last CCB of chain MOV #$CMFRK+4,R4 ; Set address of queue listhead MOV @#PS,-(SP) ; Save current priority MOVB #PR7,@#PS ;;; Disable interrupts .IF DF M$$PRO CALL $MPLCK ;;; Lock access to process queue .ENDC ; DF M$$PRO MOV R5,@2(R4) ;;; Link first to last MOV R3,2(R4) ;;; Set new last pointer CMP -(R4),-(R4) ;;; Fork block already in use ? BNE 20$ ;;; If NE, yes - just exit TST $CXOPT ;;; Are we in fork processing? BMI 20$ ;;; If MI, yes - just exit CLR (R4) ;;; Clear next link pointer .IF DF R$$MPL .IF DF M$$PRO MOV -(R5),-2(R4) ;;; Set up required Unibus Run Mask .ENDC ; DF M$$PRO CALL $QFORK ;;; Queue the fork block .IFF ; DF R$$MPL MOV R4,@$FRKHD+2 ;;; Link to end of fork list MOV R4,$FRKHD+2 ;;; Set new last pointer .ENDC ; DF R$$MPL 20$: .IF DF M$$PRO CALL @(SP)+ ;;; Co-routine return to unlock process queue .ENDC ; DF M$$PRO MOV (SP)+,@#PS ;;; Enable interrupts MOV (SP)+,R5 ; Recover R5 RETURN ; Return to caller .SBTTL $CEPWR - Powerfail Recovery Routine ;+ ; **-$CEPWR-POWERFAIL RECOVERY ROUTINE ; ; This routine is dispatched from the executive powerfail recovery ; code. It will dispatch to the AUX process with a powerfail ; recovery function code. ;- $CEPWR:: .IF DF R$$MPL MOV $DDFNC,-(SP) ; Save current function code MOV #FC.PWR,$DDFNC ; Set up powerfail function code .ENDC ; DF R$$MPL MOV #$DDFNC,R3 ; Point to powerfail recovery function code CLR R2 ; Set up PDV index (AUX is always zero) CALL $PDSPL ; and dispatch to the process .IF DF R$$MPL MOV (SP)+,$DDFNC ; Restore current function code .ENDC ; DF R$$MPL RETURN .SBTTL $LLCRQ - LLC to DLC Request Queuing Subroutine ;+ ; **- $LLCRQ - LLC TO DLC REQUEST QUEUING SUBROUTINE ; ; This routine is called by a LLC process to queue requests to ; a DLC process. Note that the callers context is saved as if ; an interrupt had occurred. ; ; Inputs: ; R4= Address of CCB (or first in chain) ; The CCB must contain a valid: ; C.FNC & C.MOD - Request function code ; C.LIN - LLC channel number (logical line number) ; ; Outputs: ; The request is dispatched to the proper DLC process ; ; Registers modified: ; None ;- $LLCRQ:: .IF DF M$$PRO SAVRG ; Save registers MOV $CMPDV,R1 ; Get current LLC PDV index ADD $PDVTA,R1 ; Point into PDV index table MOVB C.LIN(R4),R3 ; Get LLC channel number ASL R3 ; Make it a word index ADD (R1),R3 ; Point to LLC channel mapping table entry MOV Z.MAP(R3),C.LIN(R4) ; Store SLN and station address into CCB ; Note - bit15 will always be clear to ; flag destination process as a DLC MOVB C.LIN(R4),R1 ; Get system line number ASL R1 ; Form word offset ADD $SLTMA,R1 ; Point into system line index table MOV (R1),R1 ; Get address of system line table entry ;+ ; ** W a r n i n g ** ; ; DECnet-11M-PLUS V4.0 NTINIT hookpoint number 01. ; ; Do not change the instruction following label without checking NTINIT ;- $RTF01:: ; NTINIT changes the instruction at ; the location of this label MOV L.KRBA(R1),R1 ; Get pointer to KRB MOV K.URM(R1),C.URM(R4) ; Set up unibus run mask CALL $PDQU1 ; Queue request CCB and schedule process MTPS #0 ; Drop priority to 0 and clear condition codes RESRG ; Restore registers RETURN .IFF ; DF M$$PRO SAVRG ; Save all registers MOV $CMPDV,R1 ; Get current LLC PDV index ADD $PDVTA,R1 ; Point into PDV index table MOVB C.LIN(R4),R3 ; Get LLC channel number without sign extension ASL R3 ; Make it a word index ADD (R1),R3 ; Point to LLC channel mapping table entry MOV Z.MAP(R3),C.LIN(R4) ; Store SLN and station address into CCB ; Note - bit15 will always be clear to ; flag destination process as a DLC CALL $STDLC ; Set up DLC PDV index and line table address CALL $PDSPL ; Dispatch to DLC MTPS #0 ; Drop priority to 0 and clear condition codes RESRG ; Restore registers RETURN ; Return to calling LLC .ENDC ; DF M$$PRO .SBTTL $LLCRS - LLC to LLC Request Queuing Subroutine ;+ ; **- $LLCRS - LLC TO LLC REQUEST QUEUING SUBROUTINE ; **- $DLCRS - DLC TO LLC REQUEST QUEUING SUBROUTINE FOR X25 ; **- $NMCRS - LLC TO DLC REQUEST QUEUING SUBROUTINE FOR NETWORK MANAGEMENT ; ; This routine is called by a LLC process to queue requests to ; another LLC process. Note that the callers context is saved as ; if an interrupt had occurred. ; ; The $DLCRS entry point is supplied for use by the X25 data link mapping. ; ; The $NMCRS entry point is supplied for use by Network Management so that ; it can fill in the Unibus Run Mask Before issueing a request to a DLC ; for line/circuit counters etc. ; ; Inputs: ; R4= Address of CCB (or first in chain) ; The CCB must contain a valid: ; C.FNC & C.MOD - Request function code ; C.STA - Destination LLC's PDV index ; C.LIN - Option calling parameter ; ; Outputs: ; The request is queued and the appropriate level is scheduled ; ; Note: ; A LLC process can determine if a completion has come from a DLC ; process or another LLC by examining the MSB of the C.LIN/C.STA ; cell in the CCB. ; ; MSB=0 The request came from a DLC and the byte C.LIN ; contains the LLC's channel number for the logical ; line that had the completion. ; MSB=1 The request came from a LLC and the byte C.LIN ; contains an optional calling parameter from the ; requesting LLC. ; ; Registers modified: ; None ;- $DLCRS:: $LLCRS:: .IF DF M$$PRO CLR C.URM(R4) ; Allow process to run on any processor .ENDC ; DF M$$PRO $NMCRS::SAVRG ; Save R3 and R4 BIS #100000,C.LIN(R4) ; Flag destination process is LLC BISB #200,C.BID(R4) ; Mark CCB as coming from another LLC CALL $PDQU1 ; Queue request CCB and schedule process RESRG ; Restore registers RETURN ; And return to calling LLC .SBTTL $LLCLC - Process to Process Direct Call Interface (CCB) .SBTTL $LLCAL - Process to Process Direct Call Interface (No CCB) ;+ ; **-$LLCLC-PROCESS TO PROCESS DIRECT CALL INTERFACE (WITH CCB) ; **-$LLCAL-PROCESS TO PROCESS DIRECT CALL INTERFACE ; ; This routine is called by a process (typically an LLC) to dispatch to ; another process (typically another LLC) via it's dispatch table. ; ; Inputs: ; R0 = Optional calling parameter to destination process ; R1 = " " " " " " ; R2 = Process PDV index ($LLCAL only) ; R3 = Address of function code ($LLCAL only) ; R4 = Address of CCB ($LLCLC only) ; C.FNC - Function code ; C.MOD - Function modifier ; C.STA - Destination PDV index ; ; Outputs: (to the destination process) ; R3 = Subfunction code ; R4 = Address of CCB (optional) ; C.STA - Source PDV index ; R5 = Address of process database descriptor ; ; Registers modified: ; R0, R1, R2, R3, R4 ; ; Note: ; If the $LLCAL call is being performed from a task in an I and D ; space system, the word pointed to by R3 will not be accessable ; by $PDDSP because it will be mapped via Kernel Instruction APR5. ; To work around this mapping problem, the word pointed to by R3 ; should be in DSR or on the Kernel Stack. ;- $LLCLC::MOV R4,R3 ; Compute address of function code ADD #C.FNC,R3 ; ... MOVB C.STA(R4),R2 ; Get destination PDV index MOVB $CMPDV,C.STA(R4); Save source PDV index $LLCAL::SAVRG ; Save current database descriptor MOV R2,R5 ; Copy PDV index ADD $PDVTA,R5 ; Point into PDV index table MOV (R5),R5 ; Get PDV address MOV Z.DAT(R5),R5 ; Get address of database descriptor CALL $PDDSP ; Dispatch to the process RESRG ; Recover database descriptor RETURN .SBTTL $STDLC - Set up DLC Parameters for a Given SLN ;+ ; **-$STDLC-COMPUTE DLC PARAMETERS FROM A SYSTEM LINE NUMBER ; **-$STDL1-(ALTERNATE ENTRY ; ; Inputs: ; R2 = System line number (alternate entry only) ; R4 = Address of a CCB with a valid SLN in C.LIN ; (Main entry only) ; ; Outputs: ; R2 = PDV index (word offset) ; R3 = Address of function code cell in CCB ; R5 = Address of DLC line table ; ; Registers modified: ; None ;- $STDLC:: .IF NDF N$$1LN MOVB C.LIN(R4),R2 ; Get system line number .ENDC ; NDF N$$1LN $STDL1:: .IF DF N$$1LN MOV @$SLTMA,R2 ; Get address of system line table entry .IFF ; DF N$$1LN ASL R2 ; Form word index ADD $SLTMA,R2 ; Point into system line index table MOV (R2),R2 ; Get address of system line table entry .ENDC ; DF N$$1LN MOV L.DLS(R2),R5 ; Get line table address MOVB L.DLC(R2),R2 ; Get PDV index (word index) MOV R4,R3 ; Compute a pointer to the function code ADD #C.FNC,R3 ; ... RETURN ; Return to caller .SBTTL $ASCMP - Asynchronous Completion to LLC Level ;+ ; **- $ASCMP -ASYNCHRONOUS COMPLETION TO LOGICAL LINK CONTROL MODULES ; ; This routine is called by Data Link Control processes to pass ; asyncronous status/error information to higher level processes. ; ; Inputs: ; R2 = Station number and system line number ; R3 = Asynchronous status/error ; ; Outputs: ; A CCB is allocated on behalf of the caller and based on the ; system line number, is queued to the appropriate Logical ; Link Control process. ; ; Registers modified: ; R3 and R4 ;- .ENABL LSB $ASCMP::CALL $CCBGT ; Allocate a CCB BCS 30$ ; If CS error MOV #FC.CCP+FS.AST,C.FNC(R4) ; Set error complete function code MOV R2,C.LIN(R4) ; Set up station address/system line number BR 10$ ; Finish in common code .SBTTL $XMCMP - Transmit Complete to LLC Level .SBTTL $CTCMP - Control Complete to LLC Level .SBTTL $RCCMP - Receive Complete to LLC Level .SBTTL $KLCMP - Kill Complete to LLC Level ;+ ; **-$XMCMP-TRANSMIT COMPLETE TO LOGICAL LINK CONTROL PROCESSES ; **-$CTCMP-CONTROL COMPLETE ; **-$RCCMP-RECEIVE COMPLETE ; **-$KLCMP-KILL COMPLETE ; ; Inputs: ; R3 = Operation completion status ; R4 = Address of CCB (or first ccb in a chain) ; the CCB contains a valid line number ; ; Outputs: ; The appropriate function code is inserted into the CCB, ; the line number is used to find the PDV specification, and ; the CCB is added to the process queue. ; ; Registers modified: ; R3 ;- $XMCMP::MOVB #FC.XCP,C.FNC(R4) ; Set transmit complete function code BR 10$ ; Join common code $CTCMP::MOVB #FC.CCP,C.FNC(R4) ; Set control complete function code BR 10$ ; Join common code $KLCMP::MOVB #FC.KCP,C.FNC(R4) ; Set kill complete function code BR 10$ ; Join common code $RCCMP::MOVB #FC.RCP,C.FNC(R4) ; Set receive complete function code 10$: MOV R2,-(SP) ; Save callers R2 MOVB C.LIN(R4),R2 ; Get system line number 20$: MOV R3,C.STS(R4) ; Store operation status in CCB BICB #200,C.BID(R4) ; Mark message from a DLC process ASL R2 ; Multiply SLN by 2 ADD $LLCTA,R2 ; Point to reverse mapping table MOV (R2),R3 ; Get SLN & station to PDV & channel map entry BPL 25$ ; If PL, got PDV & channel (point to point) ; Else, pointer to station table map MOVB C.STA(R4),R2 ; Get station number (never sign extends) ADD R3,R2 ; Compute half mapping table entry address ASL R2 ; Make a word aligned address MOV (R2),R3 ; Get PDV & channel for this station 25$: BIS #100000,R3 ; Indicate that cell contains a PDV & channel .IF DF M$$PRO CLR C.URM(R4) ; Allow process to run on any processor .ENDC ; DF M$$PRO CALL $PDQUE ; Queue CCB and schedule process MOV (SP)+,R2 ; Restore R2 CLC ; Clear C-bit 30$: RETURN ; Return to caller .DSABL LSB .IF NDF X$$NDM .SBTTL $DD??? - DLC to DDM Requests ;+ ; General Requests with CCB ; ; Format of call: ; CALL $DD??? ; ; Inputs: ; R4 = Address of first CCB in chain ; (All CCBs must contain a valid SLN) ; ; Outputs to DDM: ; R4 = Address of first CCB in chain ; R5 = Address of DDM line table ; R2 & R3 - Available for use without saving ; ; Registers across call: ; R0,R1 - Must be preserved by DDM if used ; R2,R3,R5 - Preserved by Comm Exec ; R4 - May be modified ; ; On return to DLC: ; C-bit clear - Request has completed synchronously ; R4 = Address of CCB ; ; C-bit set - Request will complete asynchronously ; R4 = 0 ;- ;+ ; Special requests without CCB ; ; ; Format of call: ; CALL $DD??? ; ; Inputs: ; R3 = System line number ; R4 = Optional calling parameter to DDM ; ; Outputs to DDM: ; R4 = Optional calling parameter from DLC ; R5 = Address of DDM line table ; R2 & R3 - Available for use without saving ; ; Registers across call: ; R0,R1 - Must be preserved by DDM if used ; R2,R3,R5 - Preserved by Comm Exec ; R4 - May be modified ; ; On return to DLC: ; C-bit always clear ; R4 = Optional returning parameter from DDM ;- $DDXME::DDFDF FC.XME,SUB ; Transmit enable $DDRCE::DDFDF FC.RCE,SUB ; Receive enable $DDMAN::DDFDF FC.MAN,SUB ; Network management $DDXKL::DDFDF FC.KIL+FS.XKL,CCB ; Transmit kill $DDCRA::DDFDF FC.KIL+FS.CRA,CCB ; Receive kill $DDKIL::DDFDF FC.KIL+FS.KIL,CCB ; Receive and transmit kill $DDSTR::DDFDF FC.CTL+FS.STR,CCB ; Start $DDSTP::DDFDF FC.CTL+FS.STP,CCB ; Stop $DDGET::DDFDF FC.CTL+FS.GET,CCB ; Get characteristics $DDSET::DDFDF FC.CTL+FS.SET,CCB ; Set characteristics $DDRNG::DDFDF FC.CTL+FS.RNG,MDC ; Look for ring $DDENB::DDFDF FC.CTL+FS.ENB,MDC ; Enable line $DDDIS::DDFDF FC.CTL+FS.DIS,MDC ; Disable line $DDXON::DDFDF FC.CTL+FS.XON ; Xon $DDXOF::DDFDF FC.CTL+FS.XOF ; Xoff $DDMSN::DDFDF FC.CTL+FS.MSN ; Sense modem status .SBTTL DDCM1 - Common Process for Special Non-CCB Functions ;+ ; **-DDCM1 - COMMON PROCESS FOR SPECIAL NON-CCB FUNCTIONS ; ; Inputs: ; R3 = Address of function code ; R4 = Unspecified calling parameter to DDM ; Stack contains: ; 00(SP) = Line number (originally in R3) ; 02(SP) = Return address to calling DLC ; ; Outputs to DDM: ; R3 = Subfunction code (word index) ; R4 = Same as on entry ; R5 = Line table address ; ; Outputs on return to caller: ; Function has been performed ; R4 = Unspecified return parameter to DLC from DDM ; ; Registers across call: ; R2,R3,R5 preserved ; R4 may be modified by DDM ;- .ENABL LSB DDCM1: .IF DF K$$DAS MOV R3,$DDFNC ; Store function code in data area MOV #$DDFNC,R3 ; Point R3 at function code .ENDC ; DF K$$DAS MOV R2,-(SP) ; Save R2 MOV 2(SP),R2 ; Get line number BR 22$ ; Join common code to dispatch to DDM .SBTTL DDCM2 - Common Process for Modem Control Functions ;+ ; **-DDCM2 - COMMON PROCESS FOR MODEM CONTROL FUNCTIONS ; ; If the specified line has modem control enabled the ; function request is derailed to the modem controller. ; On return from the modem controller the request is ; routed to the proper DDM as usual. If the line is ; hardwired the request is routed directly to the DDM. ; ; Inputs: ; R3 = Address of function code ; R4 = Address of CCB ; Stack contains: ; 00(SP) = Caller's R3 ; 02(SP) = Return address to calling DLC ; ; Outputs to modem controller: ; R3 = Subfunction code ; R5 = Line table address ; ; Outputs to DDM: ; R3 = Subfunction code ; R4 = Same as on entry ; R5 = Line table address ; ; Outputs on return to caller: ; C-bit clear - Function performed synchronously ; C-bit set - Wait for asynchronous report of function completion ; ; Registers across call: ; R2,R3,R5 - Preserved ; R4 - Modified ;- DDCM2: .IF DF X$$MDC!R$$MPL .IF DF K$$DAS MOV R3,$DDFNC ; Store the function code in data area MOV #$DDFNC,R3 ; Point R3 at function code .ENDC ; DF K$$DAS MOV (R3),C.FNC(R4) ; Put function code in CCB MOV R2,-(SP) ; Save R2 .IF DF N$$1LN MOV $SLTMA,R2 ; Point into system line index table .IFF ; DF N$$1LN MOVB C.LIN(R4),R2 ; Get system line number ASL R2 ; Form word index ADD $SLTMA,R2 ; Point into system line index table .ENDC ; DF N$$1LN BIT #LF.MDC,@(R2)+ ; Does line need modem control? BEQ 20$ ; No - join common code to dispatch to ddm MOV R5,-(SP) ; Save register MOV R3,-(SP) ; Save address of function code CLR R2 ; Get auxilary process PDX index (always 0) MOV @$PDVTA,R5 ; Get address of auxilary process' PDV ; that works since it's PDV index = 0 MOV Z.DAT(R5),R5 ; Get address of data base descriptor block CALL $PDDSP ; Dispatch to modem controller MOV (SP)+,R3 ; Restore R3 MOVB C.LIN(R4),R2 ; Obtain line number (no sign extension) BIS #100000,C.LIN(R4) ; Indicate modem control request CALL DDMDSP ; Dispatch to the device driver (DDM) BCS 25$ ; Request will complete asynchronously CALL $CCBRT ; Otherwise return CCB to pool CLR R4 ; Modem controller will return asynchronous completion SEC ; Set C-bit, line is modem controlled BR 25$ ; Join common code .ENDC ; DF X$$MDC!R$$MPL .SBTTL DDCM3 - Common Process for Functions with CCB .SBTTL DDCM4 - Common Process for Functions with CCB ;+ ; **-DDCM3 - COMMON PROCESS FOR FUNCTIONS WITH CCB ; **-DDCM4 - COMMON PROCESS FOR FUNCTIONS WITH CCB ; ; Inputs: ; R3 = Address of function and subfunction code (DDCM3) ; R3 = Address of function code only (DDCM4) ; R4 = Address of CCB ; Stack contains: ; 00(SP) = Callers R3 ; 02(SP) = Return address to calling DLC ; ; Outputs to DDM: ; R3 = Subfunction code (word index) ; R4 = Address of CCB ; R5 = Address of line table ; ; Registers across call: ; R2,R3,R5 - Preserved ; R4 - May be modified ;- DDCM3: .IF DF K$$DAS MOV R3,$DDFNC ; Store function code in data area MOV #$DDFNC,R3 ; Point R3 at function code .IFTF ; DF K$$DAS MOV (R3),C.FNC(R4) ; Put function and subfunction in CCB BR 10$ ; Join common code DDCM4: .IFT ; DF K$$DAS MOV R3,$DDFNC ; Store function code in data area MOV #$DDFNC,R3 ; Point R3 at function code .ENDC ; DF K$$DAS MOVB (R3),C.FNC(R4) ; Put function code in CCB 10$: MOV R2,-(SP) ; Save R2 20$: MOVB C.LIN(R4),R2 ; Get SLN 22$: MOV R5,-(SP) ; Save R5 CALL DDMDSP ; Dispatch to the device driver (DDM) 25$: MOV (SP)+,R5 ; Restore R5 MOV (SP)+,R2 ; Restore R2 MOV (SP)+,R3 ; Restore R3 RETURN ; Return to calling DLC .DSABL LSB .SBTTL DDMDSP - Dispatch to DDM Level ;+ ; **-DDMDSP-DISPATCH TO DDM LEVEL ; ; This subroutine is called to dispatch down to the ddm level. Process ; dispatch will occur at the current priority or at the process priority ; dependent on a PDV flag. ; ; Inputs: ; R2 = System line number ; ; Registers modified: ; R5 ;- DDMDSP: CALL $STDD1 ; Set up DDM PDV index & line table address CLC ; Save current priority MFPS -(SP) ; with C-bit clear SAVRG ; Get a free register MOV R2,R0 ; Copy DDM PDV index ADD $PDVTA,R0 ; Point into PDV index table MOV (R0),R0 ; Get pointer to PDV BIT #ZF.DVP,Z.FLG(R0) BEQ 10$ ; If EQ, run DDM at current priority MTPS #PR7 ; Raise processor priority BICB Z.SCH(R0),PS ;;; Drop to process priority 10$: RESRG ; Restore register CALL $PDDSP ; Dispatch to the DDM ADC (SP) ; Update C-bit in saved PS MTPS (SP)+ ; Restore processor priority RETURN .SBTTL $DDAST - Asynchronous Completion to DLC Level ;+ ; **-$DDAST-ASYNCHRONOUS COMPLETION TO DATA LINK CONTROL ; ; This subroutine is called by device drivers when an asynchronous ; condition must be returned to a data link control module and no CCB ; is available at the device driver. ; ; Inputs: ; R3 = Asynchronous completion status (moved into C.STS) ; R4 = System line number ; ; Outputs: ; A CCB is allocated on behalf of the device driver ; and the asynchronous status is queued to the ; Data Link Control module with: ; C.FNC= FC.CCP ; C.MOD= FS.AST ; ; Registers modified: ; XXX ;- .ENABL LSB $DDAST::MOV R4,-(SP) ; Save line number CALL $CCBGT ; Allocate a CCB BCS 5$ ; If CS error MOV (SP)+,C.LIN(R4) ; Set line number in CCB MOV #FC.CCP+FS.AST,C.FNC(R4) ; Set error complete function code BR 20$ ; Finish in common code 5$: MOV (SP)+,R4 ; Clean the stack RETURN ; Return to caller .SBTTL $DDXMP - Transmit Complete to DLC Level .SBTTL $DDRCP - Receive Complete to DLC Level .SBTTL $DDCCP - Control Complete to DLC Level .SBTTL $DDKCP - Kill Complete to DLC Level ;+ ; **-$DDXMP-TRANSMIT COMPLETE TO DATA LINK CONTROL ; **-$DDRCP-RECEIVE COMPLETE ; **-$DDCCP-CONTROL COMPLETE ; **-$DDKCP-KILL COMPLETE ; **-$LLCSP-SPECIAL ENTRY POINT FOR X25 ; ; This subroutine is called by Device Drivers to queue ; completion notifications to Data Link Control modules. ; ; The $LLCSP entry point is provided for use by the X25 Data Link Mapping. ; ; Inputs: ; R3 = Operation completion status ; R4 = Address of CCB to queue ; The CCB contains a valid line number ; ; ; Outputs: ; The CCB is queued to a DLC list based ; on the system line number parameter in the CCB with a ; transmit or receive complete function code. ; ; Registers modified: ; XXX ;- $DDXMP::MOVB #FC.XCP,C.FNC(R4) ; Set transmit complete function code BR 20$ ; Join common code $DDRCP::MOVB #FC.RCP,C.FNC(R4) ; Set receive complete function code BR 20$ ; Join common code $DDKCP::MOVB #FC.KCP,C.FNC(R4) ; Set kill complete function code BR 20$ ; Join common code $DDCCP::TST C.LIN(R4) ; Special modem control completion? BPL 10$ ; If PL no CALLR $CCBRT ; Yes - return CCB to pool ; Modem controller will post completion 10$: MOVB #FC.CCP,C.FNC(R4) ; Set control complete function code $LLCSP:: $DDSPC:: 20$: MOV R3,C.STS(R4) ; Set completion status .IF DF M$$PRO MOVB C.LIN(R4),R3 ; Get system line # ASL R3 ; Form word offset ADD $SLTMA,R3 ; Point into system line index table MOV (R3),R3 ; Get address of system line table ;+ ; ** W a r n i n g ** ; ; DECnet-11M-PLUS V4.0 NTINIT hookpoint number 02. ; ; Do not change the instruction following label without checking NTINIT ;- $RTF02:: ; NTINIT changes the instruction at ; the location of this label MOV L.KRBA(R3),R3 ; Get pointer to KRB MOV K.URM(R3),C.URM(R4) .ENDC ; DF M$$PRO CALLR $PDQU1 ; Queue CCB and schedule process .DSABL LSB .ENDC ; NDF X$$DDM .SBTTL $STDDM - Set DDM PDV Index and Line Table Address ;+ ; **-$STDDM-SET DDM PDV INDEX AND LINE TABLE ADDRESS ; **-$STDD1-(ALTERNATE ENTRY) ; ; This subroutine is called to set up a Device Driver PDV index and ; line table address based on a system line number. ; ; Inputs: ; R2 = System line number (alternate entry only) ; R4 = CCB address with a valid system line number in ; C.LIN (Main entry only) ; ; Outputs: ; R2 = PDV index ; R5 = Address of device line table ; ; Registers modified: ; R5 ;- $STDDM:: .IF NDF N$$1LN MOVB C.LIN(R4),R2 ; Extract system line number .ENDC ; NDF N$$1LN $STDD1:: .IF DF N$$1LN MOV @$SLTMA,R2 ; Get address of system line entry .IFF ; DF N$$1LN ASL R2 ; Form word index ADD $SLTMA,R2 ; Point into system line index table MOV (R2),R2 ; Get address of system line entry .ENDC ; DF N$$1LN MOV L.DDS(R2),R5 ; Get device line table address MOVB L.DDM(R2),R2 ; Get device driver PDV index (word index) RETURN ; Return .SBTTL $CCBGT - Allocate a Standard CCB ;+ ; **-$CCBGT- Allocate a Standard CCB ; ; This subroutine is called to allocate a CCB from the CCB pool. If the ; assembly option is chosen, the CCB may be allocated from System ; Dynamic Memory if the CCB pool is empty. ; ; Inputs: ; None. ; ; Outputs: ; R4 contains the address of the allocated CCB ; C-Bit is CLEAR if the CCB was successfully allocated ; C-Bit is SET and R4=0 if the allocation failed ;- $CCBGT::CLC ; Assume Success MOV @#PS,-(SP) ; Save current priority MOVB #PR7,@#PS ;;; Disable interrupts .IF DF M$$PRO CALL $MPLCK ;;; Lock Access to CommExec Resources .ENDC ; DF M$$PRO CALL CCBGT ;;; Allocate a CCB .IF DF M$$PRO CALL @(SP)+ ;;; Co-Routine return to unlock resources .ENDC ; DF M$$PRO MOV (SP)+,@#PS ;;; Enable interrupts (and load final C-bit) RETURN .SBTTL $LDBGT - Get a Large Data Buffer ;+ ; **-$LDBGT- Get a Large Data Buffer ; ; This subroutine is called to allocate a fixed length Large Data ; Buffer. Large Data Buffers come out of the same pool as Receive ; Data Buffers. The difference is that Large Data Buffers are for ; use by non-DDM processes and there must be a minimum number of ; buffers remaining in the pool or the allocation will fail. The ; minimum number reserved for DDM processes is the RDB threshold. ; ; Inputs: ; None. ; ; Outputs: ; R4 contains the address of buffers allocated CCB ; C-Bit is CLEAR if the CCB/LDB was successfully allocated ; C-Bit is SET and R4=0 if the allocation failed ; ; Note: ; The caller's APR6 is preserved across this call. ;- $LDBGT::CMP $RDBCT,$RDBTH ; Is pool minimum threshold exceeded? BHIS $RDBGT ; If HIS, No ... go allocate buffer INC $LDBAF ; Increment count of allocation failures RETURN ; Return with C-Bit SET .SBTTL $RDBGT - Get a Receive Data Buffer ;+ ; **-$RDBGT- Get a Receive Data Buffer ; ; This subroutine is called to allocate a fixed length Receive ; Data Buffer. ; ; Inputs: ; None. ; ; Outputs: ; R4 contains the address of allocated buffer's CCB ; C-Bit is CLEAR if the CCB/RDB was successfully allocated ; C-Bit is SET and R4=0 if the allocation failed ; ; Note: ; The caller's APR6 is preserved across this call. ;- $RDBGT::MOV @#KISAR6,-(SP) ; Save current APR6 mapping SAVRG ; Save some registers CLC ; Assume successful MOV @#PS,-(SP) ; Save current priority MOVB #PR7,@#PS ;;; Disable interrupts .IF DF M$$PRO CALL $MPLCK ;;; Lock access to CommExec resources .ENDC ; DF M$$PRO CALL CCBGT ;;; Allocate a CCB BCS 10$ ;;; If CS, None available MOV #CF.LB,C.FLG(R4) ;;; Set-up last buffer indicator MOVB #CB.RDB,C.BID(R4) ;;; and buffer ID fields in CCB MOV $RDBSZ,C.CNT(R4) ;;; Load size of RDB/LDB MOV $RDBSZ,C.CNT2(R4) MOV #$RDBLH,R5 ;;; Point to listhead in allocation crtl block CALL BUFGT ;;; Allocate a Large Data Buffer BCC 10$ ;;; If CC, Successful CALL CCBRT ;;; Else, release the CCB CLR R4 ;;; No CCB available 10$: .IF DF M$$PRO CALL @(SP)+ ;;; Co-Routine return to unlock resources .ENDC ; DF M$$PRO MOV (SP)+,@#PS ;;; Enable interrupts (and load final C-bit) RESRG ; Restore registers MOV (SP)+,@#KISAR6 ; Restore previous APR6 mapping RETURN ; Return to caller .SBTTL $RDBRT - Return a Receive Data Buffer .SBTTL $LDBRT - Return a Large Data Buffer ;+ ; **-$RDBRT- Return a Receive Data Buffer ; **-$LDBRT- Return a Large Data Buffer ; ; This routine is called to return a data buffer to the large buffer ; pool. If the waiters count is zero or a buffer is already queued to ; the system process to satisfy a wait request, the buffer is returned ; to the pool. Otherwise, the system return process is scheduled. ; ; Inputs: ; R4 contains the address of buffer's CCB ; Note that C.BUF2+2 must contain the original Virtual ; Address of the buffer, and C.BUF must contain the original ; Bias of the buffer. ; ; Outputs: ; None. ;- $LDBRT:: $RDBRT::SAVRG ; Save some registers MOV @#PS,-(SP) ; Save current priority MOVB #PR7,@#PS ;;; Disable interrupts MOV C.BUF2+2(R4),C.BUF+2(R4) ;;; Copy the buffer's Virtual Address MOV #$RDBCT,R5 ;;; Point to count in allocation control block TST $RDQCT ;;; Are any processes waiting for an RDB? BLE RELBUF ;;; If LE, no waiters or buffer already queued MOV #100000,R3 ;;; Else, send to buffer return system process BIS R3,$RDQCT ;;; Mark a buffer return in progress MOV #FC.RCE!FS.RTN,C.FNC(R4) .IF DF M$$PRO CLR C.URM(R4) ;;; Allow process to run on any processor .ENDC ; DF M$$PRO CLR (R4) ;;; Clear link word (only return 1 buffer) CALL $PDQUE ;;; Queue buffer to system process BR CMNRTN ;;; Enter common code .SBTTL $CCBRT - Return a CCB ;+ ; **-$CCBRT- Return a CCB ; ; This routine is called to deallocate a standard CCB. ; ; Inputs: ; R4 contains the address of the CCB ; ; Outputs: ; None. ;- $CCBRT::MOV @#PS,-(SP) ; Save current priority MOVB #PR7,@#PS ;;; Disable interrupts .IF DF M$$PRO CALL $MPLCK ;;; Lock access to CommExec resources .ENDC ; DF M$$PRO CALL CCBRT ;;; Return the CCB .IF DF M$$PRO CALL @(SP)+ ;;; Co-Routine return to unlock resources .ENDC ; DF M$$PRO MOV (SP)+,@#PS ;;; Enable interrupts RETURN .SBTTL $CSBGT - Get a CCB and a Small Data Buffer ;+ ; **-$CSBGT- Get a CCB and a Small Data Buffer ; ; This routine is called to allocate a CCB and a Small Data Buffer. ; The routine also sets up the buffer descriptor in the CCB to point ; to the buffer as well as the proper byte count. ; ; Inputs: ; None. ; ; Outputs: ; R4 contains the address of the buffer's CCB ; C-Bit is CLEAR if the CCB/SDB was successfully allocated ; C-Bit is SET if the allocation failed ; ; Note: ; APR6 is mapped to the allocated buffer on exit. ;- .ENABL LSB $CSBGT::SAVRG ; Save some registers CLC ; Assume success MOV @#PS,-(SP) ; Save current priority MOVB #PR7,@#PS ;;; Disable interrupts .IF DF M$$PRO CALL $MPLCK ;;; Lock access to CommExec resources .ENDC ; DF M$$PRO CALL CCBGT ;;; Allocate a CCB BCS 20$ ;;; If CS, CCB allocation failed MOV #CF.LB!CF.SOM!CF.EOM,C.FLG(R4) ;;; Set last buffer and single message in MOVB #CB.SDB,C.BID(R4) ;;; in flags and load ID of CCB/SDB MOV $SDBSZ,C.CNT(R4) ;;; Load buffer size MOV $SDBSZ,C.CNT2(R4) MOV #$SDBLH,R5 ;;; Point to listhead in allocation ctrl block CALL BUFGT ;;; Allocate the buffer BCS 10$ ;;; If CS, SDB allocation failed, return CCB BR 20$ ;;; Else, enter common code .SBTTL $CSBRT - Return a CCB and a Small Data Buffer ;+ ; **-$CSBRT- Return a CCB and a Small Data Buffer ; ; This routine is called to deallocate a CCB and a Small Data Buffer ; which is pointed to by the first buffer descriptor in the CCB. ; ; Inputs: ; R4 contains the address of the CCB ; Note that C.BUF+2 must contain the original Virtual ; Address of the buffer, and C.BUF must contain the original ; Bias of the buffer. ; ; Outputs: ; None. ;- $CSBRT::SAVRG ; Save some registers MOV @#PS,-(SP) ; Save current priority MOVB #PR7,@#PS ;;; Disable interrupts MOV #$SDBCT,R5 ;;; Point to count in allocation control block RELBUF: .IF DF M$$PRO CALL $MPLCK ;;; Lock access to CommExec resources .ENDC ; DF M$$PRO MOV C.BUF(R4),R3 ;;; Set up address of the buffer MOV C.BUF+2(R4),R2 ;;; as an address double word CALL BUFRT ;;; Release the buffer 10$: CALL CCBRT ;;; Release the CCB 20$: .IF DF M$$PRO CALL @(SP)+ ;;; Co-Routine return to unlock resources .ENDC ; DF M$$PRO CMNRTN: MOV (SP)+,@#PS ;;; Enable interrupts (and load final C-bit) RESRG ; Restore registers RETURN .DSABL LSB .SBTTL $RDBWT - Queue a Request for a Receive Data Buffer ;+ ; **-$RDBWT- Queue a request for a Receive Data Buffer ; ; This routine is called by DDM processes after a failure of the ; DDM to allocate an Receive Data Buffer ($RDBGT) has occured. ; The system line table flags word is updated to mark the buffer ; wait request and the global request is incremented. ; ; Inputs: ; R4 contains the System Line Number ; ; Outputs: ; None. ;- $RDBWT::SAVRG ; Save a register .IF DF M$$PRO CALL $MPSAV ; Bypass the cache .ENDC ; DF M$$PRO ASL R4 ; Convert SLN to word offset ADD $SLTMA,R4 ; Point into System Line Index Table ;+ ; ** W a r n i n g ** ; ; DECnet-11M-PLUS V4.0 NTINIT hookpoint number 03. ; ; Do not change the instructions following ; label without checking NTINIT ;- $RTF03:: ; NTINIT changes the instructions at ; the location of this label INCB @(R4)+ ; Increment wait request count for this line NOP ; Space for NTINIT runtime code NOP ; MOV (R4),R4 ; Code replacement for DECnet-11M-PLUS V4.0 ; INCB L.BFWT(R4) ; ... INC $RDQCT ; Increment global count .IF DF M$$PRO CALL @(SP)+ ; Restore state of the cache .ENDC ; DF M$$PRO RESRG ; Restore the register RETURN .SBTTL $RDBQP - Purge Buffer Wait Queue ;+ ; **-$RDBQP- Purge Buffer Wait Queue ; ; This routine is called to cancel all requests in the Receive Data ; Buffer Wait Queue for a particular system line number. ; ; Inputs: ; R4 contains the system line number ; ; Outputs: ; None. ;- $RDBQP::SAVRG ; Save some registers .IF DF M$$PRO CALL $MPSAV ; Bypass the cache .ENDC ; DF M$$PRO ASL R4 ; Convert SLN into word offset ADD $SLTMA,R4 ; Point into System Line Index Table ;+ ; ** W a r n i n g ** ; ; DECnet-11M-PLUS V4.0 NTINIT hookpoint number 04. ; ; Do not change the instructions following ; label without checking NTINIT ;- $RTF04:: ; NTINIT changes the instructions at ; the location of this label MOV @(R4)+,R3 ; Get System Line Table flags word BIC #^C,R3 ; Isolate wait request count BIC R3,@-(R4) ; Clear wait request count in SLT NOP NOP ; MOV (R4),R4 ; Code replacement for DECnet-11M-PLUS V4.0 ; CLR R3 ; ... ; BISB L.BFWT(R4),R3 ; ... ; CLRB L.BFWT(R4) ; ... SUB R3,$RDQCT ; Reduce global wait count by same value .IF DF M$$PRO CALL @(SP)+ ; Restore state of the cache .ENDC ; DF M$$PRO RESRG ; Restore registers RETURN .SBTTL CCBGT - CCB Allocation Routine ;+ ; **-CCBGT- CCB allocation routine ; ; This subroutine is called within this module to allocate a CCB ; from the CCB pool or from System Dynamic Memory. This routine is ; always executed with interrupts inhibited (and multi-processors ; locks set). ; ; Inputs: ; None. ; ; Outputs: ; R4 contains the address of allocated CCB ; C-Bit is CLEAR if the CCB was successfully allocated ; C-Bit is SET if the allocation failed ; ; Notes: ; Before this routine is called, the calling routine must have issued ; a CLC instruction followed by an INHIB$. No other values must be ; stored on the stack because if the allocation fails, the FAIL: code ; will reach back on the stack and set the C-Bit in the saved PSW so ; that when the calling routine executes an ENABL$ the C-Bit will be ; set to indicate the allocation failure. ;- CCBGT: .IF DF N$$OPT!R$$MPL TSTB PRIOFF+2(SP) ;;; Can we dynamically allocate a CCB? BMI 10$ ;;; If MI, No CMP $CCBCT,$RDBTH ;;; Else, are we below the RDB threshold BHI 10$ ;;; If HI, No ... allocate from pool CMP $CCBAL,$RDBNM ;;; Have we allocated enough dynamic CCBs? BHIS 30$ ;;; If HIS, Yes SAVRG ;;; Save some registers MOV $CCBSZ,R1 ;;; Get size of block to allocate .IF DF M$$PRO ADD #2,R1 ;;; 2 more bytes on a Multi-Processor .ENDC ; DF M$$PRO CALL $ALOCB ;;; Try to allocate a dynamic CCB MOV R0,R4 ;;; Copy adress of allocated block RESRG ;;; Restore registers BCS 10$ ;;; If CS, DSR allocation failed .IF DF M$$PRO TST (R4)+ ;;; Skip over Unibus Run Mask .ENDC ; DF M$$PRO INC $CCBAL ;;; Count dynamically allocated CCB BR 20$ ;;; Enter common code .ENDC ; DF N$$OPT!R$$MPL 10$: MOV $CCBLH,R4 ;;; Get address of first CCB in list BEQ 30$ ;;; If EQ, list is empty MOV (R4),$CCBLH ;;; Unlink CCB from list DEC $CCBCT ;;; Reduce count of available CCBs 20$: MOVB #CB.CCB,C.BID(R4) ;;; Set up buffer ID byte .IF DF M$$PRO CLR C.URM(R4) ;;; Allow process to run on any processor .ENDC ; M$$PRO CLR (R4) ;;; Zero next pointer (clear C-Bit) RETURN ;;; Return to caller 30$: INC $CCBAF ;;; Count allocation failures BR FAIL ;;; Enter common failure processing code .SBTTL CCBRT - CCB Deallocation Routine ;+ ; **-CCBRT- CCB Deallocation Routine ; ; This subroutine is called within this module to deallocate a CCB ; to the CCB pool or to System Dynamic Memory. This routine is always ; executed with interrupts inhibited (and Multi-Processor locks set). ; ; Inputs: ; R4 contains the address of the CCB to release ; ; Outputs: ; None. ;- CCBRT: .IF DF N$$OPT!R$$MPL .IF NDF R$$MPL CMP R4,#$CEAVL ;;; Is CCB from the internal pool? BHIS 10$ ;;; If HIS, Yes .ENDC ; NDF R$$MPL TSTB PRIOFF+2(SP) ;;; Were we called from Device Priority Level? BMI 10$ ;;; If MI, Yes ... can't interlock $DEACB CMP $CCBCT,$RDBTH ;;; Can we satisfy RDB requests? BLOS 10$ ;;; If LOS, No ... return to list TST $CCBAL ;;; Any dynamic CCBS allocated? BEQ 10$ ;;; If EQ, No ... return to list .IF DF,M$$PRO ;+ ; Use the CCB as a fork block, and then deallocate the block ; to primary pool ... This will avoid any potential race conditions ; which could possibly exist in an mP environment. ;- MOV R4,6(R4) ;;; save the fork block R4 CLR -(R4) ;;; clear out the URM field in the CCB ADD #10,R4 ;;; and point to it ... DEC $CCBAL ;;; drop the count prior to fork ... CALL $FORK1 ;;; and fork into system state .IFF ;DF,M$$PRO SAVRG ;; Save some registers .IFTF ;DF,M$$PRO MOV R4,R0 ;; Copy address of CCB MOV $CCBSZ,R1 ;; Get size of block to deallocate .IFT ;DF,M$$PRO ADD #2,R1 ;; 2 more bytes on Multi-Processors TST -(R0) ;; Backup over Unibus Run Mask .IFTF ;DF,M$$PRO CALL $DEACB ;; Deallocate the CCB .IFF ;DF,M$$PRO RESRG ;; Restore the registers DEC $CCBAL ;; Decrement count of dynamic CCB's .ENDC ;DF,M$$PRO RETURN .ENDC ; DF N$$OPT!R$$MPL 10$: MOV $CCBLH,(R4) ;;; Set first pointer in returned CCB MOV R4,$CCBLH ;;; Set new first pointer INC $CCBCT ;;; Increment count of CCB's in pool RETURN .SBTTL Allocation Control Block Documentation ;+ ; Allocation Control Blocks are used to control the allocation ; of fixed length blocks from double link lists (address ; doublewords). The control blocks have the following format: ; ; .WORD <# of buffers available> ; .WORD 0,0 ; Allocation listhead ; .WORD <# of allocation failures> ;- .SBTTL BUFGT - General Buffer Allocation Routine ;+ ; **-BUFGT- General Buffer Allocation Routine ; ; This subroutine is called within this module to allocate a ; buffer from a doubley linked list. This routine is always executed ; with interrupts inhibited (and Multi-Processor locks set). ; ; Inputs: ; R5 contains the pointer to listhead in Allocation Control Block ; ; Outputs: ; R2 contains the Virtual Address of buffer ; R3 contains the APR Bias of buffer ; C-Bit is CLEAR if the buffer was successfully allocated ; C-Bit is SET if the allocation failed ; ; Registers Modified: ; R5 ; APR6 will be mapped to the buffer. ; ; Notes: ; Before this routine is called, the calling routine must have issued ; a CLC instruction followed by an INHIB$. No other values must be ; stored on the stack because if the allocation fails, the FAIL: code ; will reach back on the stack and set the C-Bit in the saved PSW so ; that when the calling routine executes an ENABL$ the C-Bit will be ; set to indicate the allocation failure. ;- BUFGT: CLC ;;; Assume success MOV (R5)+,R3 ;;; Get next buffer's APR Bias MOV (R5)+,R2 ;;; Get next buffer's Virtual Address BEQ 10$ ;;; If EQ, No more buffers available MOV R3,@#KISAR6 ;;; Map APR6 to the new buffer MOV 2(R2),-(R5) ;;; Unlink buffer from MOV (R2),-(R5) ;;; the free list MOV R3,C.BUF(R4) ;;; Load the Buffer Bias MOV R3,C.BUF2(R4) MOV R2,C.BUF+2(R4) ;;; Load the Buffer Virtual Address MOV R2,C.BUF2+2(R4) DEC -(R5) ;;; Decrement count of available buffers RETURN 10$: INC (R5)+ ;;; Increment count of allocation failures FAIL: INC PRIOFF+2(SP) ;;; Set C-Bit in saved PSW for ENABL$. SEC ;;; Indicate buffer allocation failure RETURN .SBTTL BUFRT - General Buffer Deallocation Routine ;+ ; **-BUFRT- General Buffer Deallocation Routine ; ; This routine is called within this module to deallocate a buffer ; to a doubley linked list. This routine is always called with ; interrupts inhibited (and Multi-Processor locks set). ; ; Inputs: ; R2 contains the Virtual Address of buffer ; R3 contains the APR Bias of buffer ; R5 points to the buffer count in allocation control block ; ; Outputs: ; None. ;- BUFRT: INC (R5)+ ;;; Increment count of available buffers MOV @#KISAR6,-(SP) ;;; Save current APR6 mapping MOV R3,@#KISAR6 ;;; Map APR6 to the buffer being returned MOV (R5)+,(R2) ;;; Link buffer to start MOV (R5)+,2(R2) ;;; of the free list MOV (SP)+,@#KISAR6 ;;; Restore previous APR6 mapping MOV R2,-(R5) ;;; Set new first buffer MOV R3,-(R5) ;;; pointer RETURN .SBTTL $CELOG - Log Network Event ;+ ; **-$CELOG-LOG NETWORK EVENT ; ; Inputs: ; R0 - Event class and type ; R1 - Event control word: ; Low byte: ; Bit 0 1 => R4 is address of a CCB ; 0 => R4 is a data area pointer ; ; 1 1 => Line-ID is SLN & Station ; 0 => Line-ID is PDV & Channel ; ; 2 1 => Event is associated with a line ; 0 => Event is not associated with a line ; ; 3 1 => Event is associated with a remote node ; 0 => Event is not associated with a remote node ; ; 4 1 => Event is associated with a circuit ; 0 => Event is not associated with a circuit ; ; 5 1 => Event is associated with a module ; 0 => Event is not associated with a module ; ; 6 1 => Use line-id from CCB ; 0 => Use line-id from event descriptor block ; ; High byte: ; # of bytes of data to copy ; ; R3 - Pointer to event descriptor block: ; ; Word 1 Line-ID (SLN & station or PDV & channel) ; 2-4 Event dependent data ; 5 Node address ; 6 Module ID (Coded value) ; 7 Port # ; 8 Logical channel # ; ; R4 - Pointer to CCB or data area pointer ; ; Registers modified: ; R0, R1, R2, R3, R5 ;- ; $CELOG:: .IF DF N$$EVL!R$$MPL MOV $LGPDV,R2 ; Get PDV index of logging process BEQ 10$ ; If EQ, no logging MOV $CMPDV,-(SP) ; Save calling process PDV index MOV R3,-(SP) ; Save address of event descriptor block MOV R1,-(SP) ; and event control word MOV SP,R1 ; Set up pointer to control block SAVRG ; Preserve CCB address MOV $LGDDB,R5 ; Set address of logging database MOV #$CELFN,R3 ; Set up dispatch function CALL $PDDSP ; and dispatch to logging process RESRG ; Restore CCB address CMP (SP)+,(SP)+ ; Clean up the stack TST (SP)+ ; ... .ENDC ; DF N$$EVL!R$$MPL 10$: RETURN ; And return .SBTTL $TSTIM - Timeout Processor ;+ ; **-$TSTIM-TIMEOUT PROCESSOR ; ; This subroutine is called to test and decrement a timeout count in ; the first byte of a process line table. If the count is decremented ; to zero, the process is dispatched at it's timeout entry point ; with a 'FS.LTM' subfunction code. ; ; Inputs: ; R2 - PDV index of process ; R5 - Pointer to process line table ; ; Outputs: ; Only R4 will be peserved ;- $TSTIM::MOV R2,R3 ; Copy PDV index ADD $PDVTA,R3 ; Point into PDV index table MOV @#KISAR5,-(SP) ; Save current mapping MOV @(R3)+,@#KISAR5 ; Map to process (for mapped line tables) MTPS #PR7 ;;; Disable interrupts TSTB (R5) ;;; Is the timer active? BEQ 10$ ;;; No ... just exit DECB (R5) ;;; Yes ... decrement time to go BNE 10$ ;;; If NE, timer still running CALL $DSPTM ;;; Dispatch to process 10$: MTPS #0 ;;; Restore priority MOV (SP)+,@#KISAR5 ;;; Restore mapping RETURN ; .SBTTL $DSPTM - Dispatch a Process Timeout ;+ ; **-$DSPTM-DISPATCH A PROCESS TIMEOUT ; ; Dispatch a process timeout at it's timeout entry point with a ; subfunction code of 'FS.LTM' ; ; Inputs: ; R2 - PDV index of process ; R5 - Pointer to process line table ; ; Outputs: ; Only R4 will be preserved ;- $DSPTM::MOV R4,-(SP) ;;; Save caller's R4 MOV #$LTMFC,R3 ;;; Get address of function code CALL $PDSPL ;;; Dispatch to process MOV (SP)+,R4 ;;; Restore caller's R4 MTPS #0 ;;; Enable interrupts RETURN .SBTTL $CMQIN - Queue a Chain of CCBs to a List ;+ ; **-$CMQIN - QUEUE A CHAIN OF CCBS TO A LIST ; ; This subroutine is called to add a CCB or a chain of CCBs to ; the end of a single linked list. ; ; Inputs: ; R3 = Address of two word listhead ; R4 = Address of first CCB in chain ; ; Outputs: ; The CCB is queued to the end of the list ; ; Registers modified: ; None ;- $CMQIN::SAVRG ; Save registers 10$: MOV R4,R5 ; Copy CCB address BIC #CS.LST,C.STS(R5) ; Clear last CCB in chain bit MOV (R5),R4 ; Get address of next CCB in chain BNE 10$ ; Loop till end of chain BIS #CS.LST,C.STS(R5) ; Set last CCB in chain bit MOV (SP),@2(R3) ; Link chain to end of queue MOV R5,2(R3) ; Update listhead pointer to last CCB in queue RESRG ; Restore registers RETURN ; Return .SBTTL $CMQRM - Remove a Chain of CCBs from a List ;+ ; **-$CMQRM - REMOVE A CHAIN OF CCBS FROM A LIST ; ; This subroutine is called to remove the first entry ; from a singly linked list. ; ; Inputs: ; R3 = Address of two word listhead ; ; Outputs: ; C-bit clear: ; R4 = Address of first in chain or only CCB dequeued ; C-bit set: ; Queue is empty ; ; Registers modified: ; R4 ;- $CMQRM::SEC ; Set C-bit just in case queue is empty MOV (R3),R4 ; Get address of first CCB in queue BEQ 40$ ; Return if queue is empty SAVRG ; Save a register 10$: MOV R4,R5 ; Copy first CCB in chain address BIT #CS.LST,C.STS(R5) ; Is this the last CCB in the chain? BNE 20$ ; Yes - update the listhead MOV (R5),R4 ; No - get next CCB - is this the last? BNE 10$ ; No - loop till end of chain 20$: MOV (R5),(R3) ; Set address of new first CCB in queue BNE 30$ ; Branch if queue is not empty MOV R3,2(R3) ; Otherwise close up list 30$: CLR (R5) ; Clear link pointer in the last CCB of chain RESRG ; Restore register 40$: RETURN ; Return .SBTTL $CNV18 - Convert to 18-Bit Unibus Address .SBTTL $CNV22 - Convert to 22-Bit Q-bus Address ;+ ; **-$CNV18-CONVERT TO 18-BIT UNIBUS ADDRESS ; **-$CNV22-CONVERT TO 22-BIT QBUS-22 ADDRESS ; ; This subroutine is called to convert an address doubleword ; to an 18-bit Unibus virtual addres or a 22-bit Qbus virtual ; address ; ; Inputs: ; R2 - Virtual address ; R3 - Relocation bias (physical address/100) ; ; Outputs: ; R2 - Low order 16 bits of Unibus address ; R3 - Bits 16 & 17 of Unibus address in bits 0 & 1 ; ;- .ENABL LSB $CNV22:: ; Reference label .IF DF,K$$DAS MOV R2,-(SP) ; Save virtual address TST R3 ; Buffer from exec, or common pool? BNE 5$ ; If NE, from common pool - use bias supplied MOV R2,R3 ; Get virtual in required register CLR R2 ; Set up for left shift ASHC #3,R2 ; Shift active page field from virtual ASL R2 ; Make it a word index ADD #KDSAR0,R2 ; Calculate D-space APR address MOV (R2),R3 ; Get contents of APR BR 5$ ; Join common code .ENDC ; DF,K$$DAS $CNV18:: ; Reference label TST R3 ; Buffer from exec, or comm pool? BEQ 10$ ; If EQ, it's from exec ; (in the low 16 or 20 K) ; Exec phys addr = virtual addr = unibus addr) ADD $PUMR,R3 ; Add starting UMR bias to block address MOV R2,-(SP) ; Save virtual 5$: BIC #160000,(SP) ; Clear APR selector from virtual address CLR R2 ; Initialize 18 bit value .IF DF R$$EIS ASHC #6,R2 ; Align as an 18 bit quantity .IFF ; DF R$$EIS .REPT 6 ASL R3 ; Shift low order bits ROL R2 ; into high order 2 bits for 18-bit value .ENDR .ENDC ; DF R$$EIS ADD R3,(SP) ; Add low 16 bits to saved offset in block ADC R2 ; Add overflow to bits 16 & 17 MOV R2,R3 ; Get high order bits into R3 MOV (SP)+,R2 ; and low order bits into R2 10$: RETURN ; Return .DSABL LSB .SBTTL $MVTBF - Move from Mapped Buffer to Unmapped Buffer ;+ ; **- $MVTBF - MOVE FROM MAPPED BUFFER TO UNMAPPED BUFFER ; ; This routine is called to move a block of memory (less than ; 4k words) from a buffer that is currently mapped( (either ; in system dynamic space or in the Comm Buffer Pool) to an ; unmapped buffer. Note the mapped buffer can not be in the process's ; space mapped via APR5 since it uses APR5 to map to the unmapped ; buffer. ; ; Calling format: ; JSR R1,$MVTBF ; ; Inputs: ; R2 = Virtual address of mapped "from" buffer ; R3 = Number of bytes to move on the stack: ; ---------- ; ! R1 ! Original contents of R1 before call ; !--------! ; ! VA ! 16-bit virtual address of unmapped "to" buffer ; !--------! ; ! BIAS ! Relocation bias of unmapped "to" buffer ; ---------- ; ; Outputs: ; R2 = Updated address of "from" buffer points to last byte moved +1 ; R3 = Zero ; ; Still mapped to "from" buffer via KISAR6 ; ; Registers modified: ; R2 & R3 ;- .ENABL LSB $MVTBF::MOV KISAR5,-(SP) ; Save current process mapping MOV 6(SP),KISAR5 ; Map to "to" buffer MOV R1,6(SP) ; Save return address MOV 4(SP),R1 ; Get "to" buffer virtual address CMP #140000,R1 ; Is the "to" buffer in the exec pool? BHI 10$ ; If HI, yes then don't alter the virtual adddress SUB #20000,R1 ; Set VA for bias via KISAR5 10$: MOVB (R2)+,(R1)+ ; Move buffer a byte at a time SOB R3,10$ ; Loop till done BR 20$ ; Join common exit code .SBTTL $MVFBF - Move from Unmapped Buffer to a Mapped Buffer ;+ ; **- $MVFBF - MOVE FROM UNMAPPED BUFFER TO A MAPPED BUFFER ; ; This routine is called to move a block of memory (less than ; 4K words) from an unmapped buffer to a buffer that is currently ; mapped (either in system dynamic space or in the Comm Buffer Pool). ; The routine unmaps the requesting process and uses ARP5 to map ; to the unmapped "from" buffer. ; ; Calling format: ; JSR R1,$MVFBF ; ; Inputs: ; R2 = Virtual address of mapped "to" buffer ; R3 = Number of bytes to move on stack: ; ---------- ; ! R1 ! Original contents of R1 before call ; !--------! ; ! VA ! 16-bit virtual address of unmapped "from" buffer ; !--------! ; ! BIAS ! Relocation bias of unmapped "from" buffer ; ---------- ; ; Outputs: ; R2 = Updated address of "to" buffer points to last byte moved +1 ; R3 = Zero ; ; Still mapped to "to" buffer via KISAR6 ; ; Registers modified: ; R2 & R3 ;- $MVFBF::MOV KISAR5,-(SP) ; Save current process mapping MOV 6(SP),KISAR5 ; Map to "from" buffer MOV R1,6(SP) ; Save return address MOV 4(SP),R1 ; Get "from" buffer virtual address CMP #140000,R1 ; Is the "from" buffer in the exec pool? BHI 15$ ; If hi, yes then don't alter the virtual address SUB #20000,R1 ; Set VA for bias via KISAR5 15$: MOVB (R1)+,(R2)+ ; Move buffer a byte at a time SOB R3,15$ ; Loop till done 20$: MOV (SP)+,KISAR5 ; Restore process mapping MOV (SP)+,R1 ; Restore register TST (SP)+ ; Clean up stack RETURN ; Return .DSABL LSB .SBTTL $CALLX - Mapped Subroutine Call ;+ ; **-$CALLX-MAPPED SUBROUTINE CALL TO ANOTHER PROCESS ; ; Calling sequence: ; JSR R5,$CALLX ; .WORD
; .RAD50 ; ; Note that this subroutine assumes that the named process exists in the ; system and does not check if the process is loaded. ;- .IIF NDF K$$DAS OFS=6 ; Stack offset for R5 .IIF DF K$$DAS OFS=10 ; Stack offset for R5 $CALLX::MOV $CMPDV,-(SP) ; Save current PDV index MOV KISAR5,-(SP) ; and current process mapping .IF DF K$$DAS MOV KINAR5,-(SP) ; Save instruction mapping .ENDC ; DF K$$DAS MOV (R5)+,-(SP) ; Save destination subroutine address SAVRG ; Get 2 free registers MOV $PDVTA,R1 ; Point to PDV index table 10$: MOV (R1)+,R2 ; Get pointer to next PDV BEQ 10$ ; Ignore zero entries CMP Z.NAM(R2),(R5) ; Do we have a match? BNE 10$ ; If NE, no TST (R5)+ ; Skip over process name MOV (R2),KISAR5 ; Map to destination process .IF DF K$$DAS MOV (R2),KINAR5 ; Also map instruction space .ENDC ; DF K$$DAS TST -(R1) ; Back up PDV index table pointer SUB $PDVTA,R1 ; Compute PDV index MOV R1,$CMPDV ; and save it MOV OFS+4(SP),R2 ; Swap old R5 and return address MOV R5,OFS+4(SP) ; ... MOV R2,R5 ; ... RESRG ; Restore registers CALL @(SP)+ ; Call the subroutine .IF DF K$$DAS MOV (SP)+,KINAR5 ; Restore instruction mapping .ENDC ; DF K$$DAS MOV (SP)+,KISAR5 ; Restore process mapping MOV (SP)+,$CMPDV ; Restore current PDV index RETURN .SBTTL $CEACC - Access Block in Extended Pool .SBTTL $CECAC - Access Block in Alternate Extended Pool ;+ ; **-$CEACC-ACCESS BLOCK IN EXTENDED POOL ; **-$CECAC-ACCESS BLOCK IN ALTERNATE EXTENDED POOL ; ; This subroutine maps to a block in extended single word pool, ; and returns a virtual address to access the block. If the ; $CECAC entry is called, the Extended Pool must already be mapped ; via APR6. ; ; Inputs: ; 2(SP) = Address of block to be accessed ; KISAR6 mapped to alternate Extended Pool Base ($CECAC) ; ; OUTPUTS: ; 2(SP) = VIRTUAL ADDRESS OF MAPPED BLOCK ; ; Note: ; KISAR6 always mapped into Extended Pool on exit even if block ; is in DSR. ;- $CEACC::MOV $XBIAS,KISAR6 ; Map to base address of pool $CECAC::BIT #1,2(SP) ; Is the block in Extended Pool ? BEQ 100$ ; If EQ, no - already mapped to it SAVRG ; Else, save R0 MOV 4(SP),R0 ; Copy block address BIC #177701,4(SP) ; Return virtual address BIS #140000,4(SP) ; ... mapped through KISAR6 .IF DF R$$EIS ASH #-6,R0 .IFF ; DF R$$EIS .REPT 6 ROR R0 ; Convert address to block bias .ENDR .ENDC ; DF R$$EIS BIC #176000,R0 ; Clear extraneous bits ADD R0,KISAR6 ; ... update to proper block RESRG ; Restore R0 100$: RETURN ; Return to the caller .SBTTL $PDVID - Process Name to PDV Index ;+ ; **- $PDVID - PROCESS NAME TO PDV INDEX ; ; This subroutine maps a process name (up to three characters in RAD50) ; into a PDV index. ; ; Inputs: ; R2 = Process name (RAD50) ; ; Outputs: ; R2 = PDV Index ;- $PDVID::SAVRG ; Save registers MOV $PDVTA,R0 ; Get address of PDV address table MOV $PDVNM,-(SP) ; Get total number of PDVs in system 10$: MOV (R0)+,R1 ; Get address of PDV BEQ 15$ ; Process not loaded - go to next one CMP Z.NAM(R1),R2 ; Does process name match? BEQ 20$ ; Yes - go calculate index 15$: DEC (SP) ; Decrement count - done looping? BNE 10$ ; If NE, no SEC ; Yes - no match BR 25$ ; Return with C-bit set 20$: MOV R0,R2 ; Get current position in PDV address table SUB $PDVTA,R2 ; Subtract starting address of table TST -(R2) ; Get PROCESS pdv index 25$: INC (SP)+ ; Clean up stack and don't change C-bit RESRG ; Restore registers RETURN ; Return .SBTTL $CEMUL - Unsigned Multiply ;+ ; **- $CEMUL - UNSIGNED MULTIPLY ; ; This subroutine performs unsigned multiplication where the result is less ; than 16 bits. It is included here so that we can conditionalise the code ; for extended instruction set. ; ; Note that it is the callers responsibility to ensure that the result ; will fit in 16 bits. ; ; Inputs: ; R0 = Multiplier ; R1 = Multiplicand ; ; Outputs: ; R0 = Corrupted ; R1 = Low 16 bits of result ;- $CEMUL:: .IF DF R$$EIS MUL R0,R1 ; Perform multiplication RETURN .IFF ; DF R$$EIS CALLR $MUL ; Call exec multiply routine .ENDC ; DF R$$EIS .SBTTL $CEDIV - Unsigned Division ;+ ; **- $CEDIV - UNSIGNED DIVISION ; ; This subroutine performs unsigned division where the results are less than ; 16 bits. it is included here so that we can conditionalise the code for ; extended instruction set. ; ; Note that it is the callers responsibility to ensure that the results will ; fit in 16 bits. ; ; Inputs: ; R0 = Dividend ; R1 = Divisor ; ; Outputs: ; R0 = Quotient ; R1 = Remainder ;- $CEDIV:: .IF DF R$$EIS MOV R1,-(SP) ; Save divisor MOV R0,R1 ; Set up dividend CLR R0 ; Clear high order word DIV (SP)+,R0 ; Perform the division RETURN .IFF ; DF R$$EIS CALLR $DIV ; Call exec divide routine .ENDC ; DF R$$EIS .IF DF M$$PRO .SBTTL $MPLCK - Multi-Processor Lock Routine ;+ ; **-$MPLCK-MULTI-PROCESSOR LOCK ROUTINE ; ; This routine will perform a spin lock on the Comm Exec Lock ($CRESL) ; and then co-call the caller. On return it will unlock the Comm Exec ; lock and return. Note that we perform the lock operation ourselves ; so that we can correctly manipulate the cache. ;- $MPLCK::ASRB $CRESL ; Spin on the lock BCC $MPLCK ; until we have access CACHE$ FLUSH ; Flush the cache of stale data CALL @(SP)+ ; Co-call the caller back MOVB #1,$CRESL ; Reset the lock RETURN .SBTTL $MPSAV - Bypass Cache with Save and Restore ;+ ; **-$MPSAV-BYPASS CACHE WITH SAVE AND RESTORE ; ; This routine will save the current state of the cache and bypass ; it before co-calling the caller. On return it will restore the ; initial state of the cache. ;- $MPSAV::CACHE$ SAVE ; Save current state of cache CALL @2(SP) ; Co-call the caller MOV (SP)+,2(SP) ; Overwrite return link CACHE$ UNSAVE ; Restore the cache RETURN .ENDC ; DF M$$PRO $CEXND:: ; For release of CEX space to DSR. .ENDC ; DF M$$NET .END